import java.util.LinkedList;
import java.util.Queue;
public class Multichannel_job {
    public static void main(String[] args) {
        arithmetic a=new arithmetic();
        a.FCFS();
        System.out.println();
        a.SJF();
        System.out.println();
        a.HRRF();
    }
}

class arithmetic{
    public JCB[] jcbs;
    public int systemMainStore=100;//系统主存
    public int systemResource=4;//系统资源
    Queue<JCB> Ready=new LinkedList<JCB>();//就绪队列
    boolean run=false;
    public JCB jcb=new JCB();
    // 作业控制块
    class JCB{
        StringBuffer name = new StringBuffer("");//作业名
        int enterTime;//进入时间
        int runTime;//运行时间
        int jobTime;//作业调度时间
        int courseTme;//进程调度时间
        int mainStore;//主存需求量
        int resource;//系统资源需求量
        int endTime;//结束时间
        int revolveTime;//周转时间
        double revolvesTime;//带权周转时间
        boolean ready=false;
        boolean wait=false;
        boolean ran=false;
        double hrrf;
    }

    public void run(int i){
        for(int j=0;j<=4;j++)
        {
            if(jcbs[j].enterTime==i&&jcbs[j].wait==false)//查询当前时间是否有作业进入
            {
                jcbs[j].wait=true;
            }
        }
        for(int j=0;j<=4;j++)
        {
            if(jcbs[j].wait==true&&jcbs[j].mainStore<=systemMainStore&&jcbs[j].resource<=systemResource&&jcbs[j].ready==false)//查询当前作业是否满足进入就绪队列
            {
                jcbs[j].ready=true;
                systemMainStore=systemMainStore-jcbs[j].mainStore;
                systemResource=systemResource-jcbs[j].resource;
                Ready.add(jcbs[j]);
                jcbs[j].jobTime=i;
            }
        }

        if(run==false&&Ready!=null&&Ready.peek()!=null){
            jcb=Ready.poll();
            jcb.courseTme=i;
            run=true;
        }

        if(jcb!=null&&i==(jcb.courseTme+jcb.runTime)){
            run=false;
            jcb.endTime=(i);
            systemResource=systemResource+jcb.resource;
            systemMainStore=systemMainStore+jcb.mainStore;

            for(int j=0;j<=4;j++)
            {
                if(jcbs[j].enterTime==i&&jcbs[j].wait==false)//查询当前时间是否有作业进入
                {
                    jcbs[j].wait=true;
                }
                if(jcbs[j].wait=true&&jcbs[j].mainStore<=systemMainStore&&jcbs[j].resource<=systemResource&&jcbs[j].ready==false)//查询当前作业是否满足进入就绪队列
                {
                    jcbs[j].ready=true;
                    systemMainStore=systemMainStore-jcbs[j].mainStore;
                    systemResource=systemResource-jcbs[j].resource;
                    Ready.add(jcbs[j]);
                    jcbs[j].jobTime=i;
                }
            }

            if(run==false&&Ready!=null&&Ready.peek()!=null){
                jcb=Ready.poll();
                jcb.courseTme=i;
                run=true;
            }
        }
    }
// 先来先服务算法
    public void FCFS(){
        ready();
        for(int i=0;i<=120;i++)
        {
            run(i);
        }
        sortEnd();
        System.out.println("FCFS（先来先服务）:");
        calculate();
        print();
    }
// 最短作业优先算法
    public void SJF()
    {
        ready();
        sortRun();

        for(int i=0;i<=120;i++)
        {
            run(i);
        }
        sortEnd();
        System.out.println("SJF（最短作业优先）:");
        calculate();
        print();
    }
// 响应比高者优先算法
    public void HRRF(){
        ready();

        for(int i=0;i<=120;i++)
        {
            calculateHRRF(i);
            run(i);
        }
        sortEnd();
        System.out.println("HRRF（响应比高者优先）:");
        calculate();
        print();
    }


    public void sortRun(){
        JCB J=new JCB();
        for (int i=0;i<5;i++){
            for (int j=i+1;j<5;j++){
                if(jcbs[i].runTime>jcbs[j].runTime){
                    J=jcbs[i];
                    jcbs[i]=jcbs[j];
                    jcbs[j]=J;
                }
            }
        }
    }

    public void sortEnd(){
        JCB J=new JCB();
        for (int i=0;i<5;i++){
            for (int j=i+1;j<5;j++){
                if(jcbs[i].endTime>jcbs[j].endTime){
                    J=jcbs[i];
                    jcbs[i]=jcbs[j];
                    jcbs[j]=J;
                }
            }
        }
    }

    public void sortHRRF(){
        JCB J=new JCB();
        for (int i=0;i<5;i++){
            for (int j=i+1;j<5;j++){
                if(jcbs[i].hrrf<jcbs[j].hrrf){
                    J=jcbs[i];
                    jcbs[i]=jcbs[j];
                    jcbs[j]=J;
                }
            }
        }
    }
// 输出内容
    public void print()
    {
        double sumRevolveTime=0;
        double sumRevolvesTime=0;
        System.out.print("作业名称"+"\t");
        System.out.print("进入时间"+"\t");
        System.out.print("运行时间"+"\t");
        System.out.print("作业调度"+"\t");
        System.out.print("进程调度"+"\t");
        System.out.print("结束时间"+"\t");
        System.out.print("周转时间"+"\t");
        System.out.println("带权周转时间"+"\t");
        for(int i=0;i<5;i++) {
            System.out.print(jcbs[i].name + "\t");
            System.out.print(jcbs[i].enterTime + "\t\t");
            System.out.print(jcbs[i].runTime + "\t\t");
            System.out.print(jcbs[i].jobTime + "\t\t");
            System.out.print(jcbs[i].courseTme + "\t\t");
            System.out.print(jcbs[i].endTime + "\t\t");
            System.out.print(jcbs[i].revolveTime + "\t\t");
            sumRevolveTime=sumRevolveTime+jcbs[i].revolveTime;
            System.out.println(String.format("%.2f",jcbs[i].revolvesTime ) + "\t\t");
            sumRevolvesTime=sumRevolvesTime+jcbs[i].revolvesTime;
        }
        System.out.println("作业平均周转时间为 "+sumRevolveTime/5);
        System.out.println("作业平均带权周转时间为 "+String.format("%.2f",sumRevolvesTime/5 ));
    }

    public void calculate()//计算周转时间和带权周转时间
    {
        for(int i=0;i<5;i++) {
            jcbs[i].revolveTime=jcbs[i].endTime-jcbs[i].enterTime;
            jcbs[i].revolvesTime=jcbs[i].revolveTime*1.0/jcbs[i].runTime;
        }
    }

    public void calculateHRRF(int a)//计算响应比
    {
        for (int i=0;i<5;i++){
            if((a-jcbs[i].enterTime)>=0){
                jcbs[i].hrrf=(((a-jcbs[i].enterTime)+jcbs[i].runTime)*1.0/jcbs[i].runTime);
            }else{
                jcbs[i].hrrf=0;
            }
        }
        sortHRRF();
    }

    public void ready(){
        jcb=new JCB();
        jcbs = new JCB[5];
        for(int i = 0;i < 5;i++) {
            jcbs[i] = new JCB();
            jcbs[i].ready=false;
            jcbs[i].wait=false;
        }
        jcbs[0].name.append("JOB1");
        jcbs[0].enterTime=0;
        jcbs[0].runTime=40;
        jcbs[0].mainStore=35;
        jcbs[0].resource=3;
        jcbs[1].name.append("JOB2");
        jcbs[1].enterTime=10;
        jcbs[1].runTime=30;
        jcbs[1].mainStore=70;
        jcbs[1].resource=1;
        jcbs[2].name.append("JOB3");
        jcbs[2].enterTime=15;
        jcbs[2].runTime=20;
        jcbs[2].mainStore=50;
        jcbs[2].resource=3;
        jcbs[3].name.append("JOB4");
        jcbs[3].enterTime=35;
        jcbs[3].runTime=10;
        jcbs[3].mainStore=25;
        jcbs[3].resource=2;
        jcbs[4].name.append("JOB5");
        jcbs[4].enterTime=40;
        jcbs[4].runTime=5;
        jcbs[4].mainStore=20;
        jcbs[4].resource=2;
    }
}
